﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Company.Core.Helpers;
using Company.Shell.Dialogs;
using Company.Shell.Enums;
using Company.Shell.Interfaces;
using Company.Shell.Models;
using Company.Shell.Styles;
using Company.Shell.ViewModels;
using Company.Shell.Views;
using HandyControl.Controls;
using LiveCharts;
using LiveCharts.Defaults;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.TextFormatting;


namespace Company.Shell.Services
{
    public class ProgramManager : ObservableObject, IProgramManager
    {
        private static readonly string path = Path.Combine(Environment.CurrentDirectory, "Programs");
        private static readonly string extensionName = ".json";
        private ObservableCollection<ProgramEntity> programs = [];
        public ObservableCollection<ProgramEntity> Programs
        {
            get => programs;
            set => SetProperty(ref programs, value);
        }
        private ProgramEntity program = new();
        public ProgramEntity Program
        {
            
            get => program;
            set => SetProperty(ref program, value);
        }
        private ChartValues<ObservablePoint> temperatures = [];
        public ChartValues<ObservablePoint> Temperatures
        {
            get => temperatures;
            set => SetProperty(ref temperatures, value);
        }
        private ObservablePoint temperature = new();
        public ObservablePoint Temperature
        {
            get => temperature;
            set => SetProperty(ref temperature, value);
        }
        private ChartValues<ObservablePoint> humidities = [];
        public ChartValues<ObservablePoint> Humidities
        {
            get => humidities;
            set => SetProperty(ref humidities, value);
        }
        private ObservablePoint humidity = new();
        public ObservablePoint Humidity
        {
            get => humidity;
            set => SetProperty(ref humidity, value);
        }
        private Visibility showTemperature = Visibility.Collapsed;
        public Visibility ShowTemperature
        {
            get => showTemperature; 
            set => SetProperty(ref showTemperature, value);
        }
        private Visibility showHumidity = Visibility.Collapsed;
        public Visibility ShowHumidity
        {
            get => showHumidity; 
            set => SetProperty(ref showHumidity, value);
        }
        public ICommand SelectProgramCommand { get;  }

        public ICommand? CreateProgramCommand { get; }
        public ICommand? SaveProgramCommand { get; }
        public ICommand? DeleteProgramCommand { get; }

        private IMouseManager MouseManager { get; }
        private IDialogService DialogService { get; }
        public Func<double, string> XFormatter { get; set; }
        public Func<double, string> YFormatter { get; set; }

        public ProgramManager(IMouseManager mouseManager, IDialogService dialogService)
        {
            XFormatter = GetXFormatter();
            YFormatter = GetYFormatter();
            MouseManager = mouseManager;
            DialogService = dialogService;
            SelectProgramCommand = new RelayCommand(OnSelectProgramCommand);
            CreateProgramCommand = new RelayCommand(OnCreateProgramCommand);
            SaveProgramCommand = new AsyncRelayCommand(OnSaveProgramCommand);
            DeleteProgramCommand = new RelayCommand<ObservablePoint>(OnDeleteProgramCommand);

            LoadPrograms();
        }

        private Func<double, string>? GetYFormatter()
        {
            return value => {
                return value.ToString("F1");
            };
        }

        private Func<double, string>? GetXFormatter()
        {
            return value => {
                int totalMinutes = (int)value;
                int hours = totalMinutes / 60;
                int minutes = totalMinutes % 60;
                return $"{hours:D2} : {minutes:D2}";
            };
        }

        private async Task OnSaveProgramCommand()
        {
            if (string.IsNullOrEmpty(Program.Guid))
            {
                //保存新程序
                var t = await DialogService.ShowDialogAsync<ProgrameNameView, ProgrameNameViewModel, string>();
                if (t.Success == true && !string.IsNullOrEmpty(t.Result))
                {
                    await Save(t.Result);
                    return;
                }
              
            }
            else
            {
                //更新已有程序
                await Save(Program.Name);
            }
        }

        private void OnCreateProgramCommand()
        {
            Program = new ProgramEntity();
            Temperatures = Program.Temperature;
            Humidities = Program.Humidities;
        }

        private void OnSelectProgramCommand()
        {
            Temperatures = Program.Temperature;
            Humidities = Program.Humidities;
            MouseManager.WorkMode = Enums.MouseWorkMode.默认操作;
            showTemperature = Visibility.Visible;
            showHumidity = Visibility.Visible;


        }

        public async Task Save(string filename = "")
        {
            await Task.Run(() =>
            {
                if (string.IsNullOrEmpty(Program.Guid))
                {
                    //保存新程序
                    Program.Guid = Guid.NewGuid().ToString();//生成唯一标识符
                    Program.Name = filename;
                    Program.Temperature = Temperatures;
                    Program.Humidities = Humidities;
                    Directory.CreateDirectory(path);//创建目录
                    string fullname = $"{path}\\{Program.Name}{extensionName}";//完整路径
                    JsonHelper.Save(Program, fullname, indented: true);//保存文件
                    AddProgram(program);
                }
                else
                {
                    //更新已有程序
                    Program.Temperature = Temperatures;
                    Program.Humidities = Humidities;
                    Directory.CreateDirectory(path);//创建目录
                    string fullname = $"{path}\\{Program.Name}{extensionName}";//完整路径
                    JsonHelper.Save(Program, fullname, indented: true);//保存文件
                }
            });
            Dialog.Show<MessageDialog>();
        }
        private void AddProgram(ProgramEntity program)
        {
            App.Current.Dispatcher.Invoke(() =>
            {
                Programs.Add(program);
            });
        }
        private void LoadPrograms()
        {
            DirectoryInfo directoryInfo = new(path);
            if (directoryInfo.Exists)
            {
                var files =
                    directoryInfo.GetFiles().
                    Where(t => t.Extension.ToLower() == extensionName.ToLower());//只加载指定后缀名的文件
                foreach (var file in files)
                {
                    var program = JsonHelper.Load<ProgramEntity>(file.FullName);
                    Programs.Add(program);
                }
                // 自动选择第一个程序
                if (Programs.Count > 0 && Program?.Guid == null)
                {
                    Program = Programs.First();
                }
            }
        }

        public void Add(ObservablePoint point, MouseWorkMode mode)
        {
            var collection = mode switch
            {
                MouseWorkMode.编制温度 => Temperatures,
                MouseWorkMode.编制湿度 => Humidities,
                _ => null
            };

            if (collection is null) return;

            AddPointToCollection(collection, point);
        }

        private static void AddPointToCollection(ChartValues<ObservablePoint> collection, ObservablePoint point)
        {
            if (collection.Count == 0)
            {
                point.X = 0;
                collection.Add(point);
                return;
            }

            var insertIndex = collection.TakeWhile(item => point.X >= item.X).Count();
            collection.Insert(insertIndex, point);
        }

        private void OnDeleteProgramCommand(ObservablePoint? parameter)
        {
            // 根据当前工作模式确定要删除的数据类型
            if (MouseManager.WorkMode == MouseWorkMode.编制温度)
            {
                if (Temperature != null && Temperatures.Contains(Temperature))
                {
                    Temperatures.Remove(Temperature);
                    // 重新选择第一个项目或清空选择
                    Temperature = Temperatures.FirstOrDefault() ?? new ObservablePoint();
                }
            }
            else if (MouseManager.WorkMode == MouseWorkMode.编制湿度)
            {
                if (Humidity != null && Humidities.Contains(Humidity))
                {
                    Humidities.Remove(Humidity);
                    // 重新选择第一个项目或清空选择
                    Humidity = Humidities.FirstOrDefault() ?? new ObservablePoint();
                }
            }
            else if (parameter is ObservablePoint point)
            {
                // 如果传入了具体的点对象，直接删除
                if (Temperatures.Contains(point))
                {
                    Temperatures.Remove(point);
                }
                else if (Humidities.Contains(point))
                {
                    Humidities.Remove(point);
                }
            }
        }
    }
}
